extends Node

signal followed_channel
signal unfollowed_channel


func get_channel_urls(data: Dictionary) -> Array:
	"""
	Args:
		data: A single result from resolving a LBRY URL or claim search et
			cetera
	
	Returns:
		The permanent and short URLs of the channel in `data`. If `data` is a
		repost then the channel that is reposing is the one returned. If a URL
		can't be found then it will be an empty string
	"""
	var permanent_url: String = data \
			.get("reposted_claim", data) \
			.get("signing_channel", {}) \
			.get("permanent_url", "")
	var short_url: String = data \
			.get("reposted_claim", data) \
			.get("signing_channel", {}) \
			.get("short_url", "")
	
	# This section will find the channel URLs if `data` is from the result of
	# resolving a channel URL
	if permanent_url == "" and short_url == "":
		var prefix_length: int = len("lbry://")
		# Check that the URLs only contain the channel URLs and not that of
		# some media
		if (
				data.get("permanent_url", "").find("@") == prefix_length
				and data.get("permanent_url", "") \
					.find("/", prefix_length) == -1
		):
			permanent_url = data.get("permanent_url", "")
		if (
				data.get("permanent_url", "").find("@") == prefix_length
				and data.get("short_url", "").find("/", prefix_length) == -1
		):
			short_url = data.get("short_url", "")
	
	return [permanent_url, short_url]


func set_followed_channels(followed_channels: Array) -> void:
	var preference_key: String = "local"
	
	var preference_response: Dictionary = \
			yield(SDK.preference_get(), "completed")
	var preference_value: Dictionary = preference_response \
			.get("result", {}) \
			.get(preference_key, {}) \
			.duplicate(true)
	if not preference_value.has("value"):
		preference_value["value"] = {}
	preference_value["value"]["subscriptions"] = followed_channels
	yield(SDK.preference_set(preference_key, preference_value), "completed")


func get_followed_channels() -> Array:
	"""
	Returns:
		The followed channels
	"""
	var preference_response: Dictionary = \
			yield(SDK.preference_get(), "completed")
	return preference_response \
			.get("result", {}) \
			.get("local", {}) \
			.get("value", {}) \
			.get("subscriptions", [])


func follow_channel(channel_url: String) -> void:
	"""
	Adds the channel to the list of followed channels in preferences
	
	Args:
		channel_url: LBRY URL of the channel (permanent or short)
	"""
	var channel_urls: Array = []
	var data: Dictionary = {}
	
	# Get each type of the channel's URLs
	var resolve_response: Dictionary = \
			yield(SDK.resolve([channel_url]), "completed")
	if resolve_response.has("result"):
		data = resolve_response["result"] \
				.get(resolve_response["result"].keys()[0], {})
	if not data.empty():
		channel_urls = get_channel_urls(data)
	
	# Remove empty channel URLs
	for i in range(len(channel_urls) - 1, -1, -1):
		if channel_urls[i] == "":
			channel_urls.remove(i)
	
	if len(channel_urls) > 0:
		SDK.preference_mutex.lock()
		var followed_channels: Array = \
				yield(get_followed_channels(), "completed")
		
		var is_channel_followed: bool = false
		for url in channel_urls:
			if url in followed_channels:
				is_channel_followed = true
				break
		
		if not is_channel_followed:
			followed_channels.append(channel_urls[0])
			followed_channels.sort_custom(self, "_case_insensitive_sort")
			yield(set_followed_channels(followed_channels), "completed")
			emit_signal("followed_channel", channel_urls[0])
		SDK.preference_mutex.unlock()


func unfollow_channel(channel_url: String) -> void:
	"""
	Removes the channel from the list of followed channels in preferences
	
	Args:
		channel_url: LBRY URL of the channel (permanent or short)
	"""
	var channel_urls: Array = []
	var data: Dictionary = {}
	
	# Get each type of the channel's URLs
	var resolve_response: Dictionary = \
			yield(SDK.resolve([channel_url]), "completed")
	if resolve_response.has("result"):
		data = resolve_response["result"] \
				.get(resolve_response["result"].keys()[0], {})
	if not data.empty():
		channel_urls = get_channel_urls(data)
	
	# Remove empty channel URLs
	for i in range(len(channel_urls) - 1, -1, -1):
		if channel_urls[i] == "":
			channel_urls.remove(i)
	
	if len(channel_urls) > 0:
		SDK.preference_mutex.lock()
		var followed_channels: Array = \
				yield(get_followed_channels(), "completed")
		
		# Remove the channel's URLs from the list of followed channels
		var channel_removed: bool = false
		for url in channel_urls:
			var idx: int = followed_channels.find(url)
			if idx != -1:
				followed_channels.remove(idx)
				channel_removed = true
		
		if channel_removed:
			set_followed_channels(followed_channels)
			emit_signal("unfollowed_channel", channel_urls[0])
		SDK.preference_mutex.unlock()


func is_lbry_url(url: String) -> bool:
	return url.begins_with("lbry://")


func _case_insensitive_sort(a: String, b: String) -> bool:
	return a.to_lower() < b.to_lower()
